package com.kgc.sbt.provider;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;;
import com.kgc.sbt.api.OrderInfoApi;
import com.kgc.sbt.api.OrderItemApi;
import com.kgc.sbt.api.WxPayApi;
import com.kgc.sbt.config.WxpayConfig;
import com.kgc.sbt.constant.ActiveMqConstant;
import com.kgc.sbt.constant.SystemConstant;
import com.kgc.sbt.domain.TempOrderInfo;
import com.kgc.sbt.mapper.WxPayMapper;
import com.kgc.sbt.util.HttpClient4Util;
import com.kgc.sbt.util.WxpayUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.util.StringUtils;
import redis.clients.jedis.Jedis;

import javax.jms.Destination;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

/**
 * Created on 2021/6/23.
 * <p>
 * Author: yx
 * <p>
 * Description:
 */
@Service
@Slf4j
public class WxPayProvider implements WxPayApi {
    // 静态注入redis
    private static Jedis jedis = new Jedis("127.0.0.1", 6379);

    static {
        // 用0库进行测试
        jedis.select(0);
    }


    @Autowired
    private WxpayConfig wxpayConfig;

    @Autowired
    private WxPayMapper wxPayMapper;

    @Autowired(required = false)
    private JmsMessagingTemplate jmsMessagingTemplate;

    @Reference
    private OrderInfoApi orderInfoApi;

    @Reference
    private OrderItemApi orderItemApi;


    @Override
    public String getWxpayOrderParamsXmlStr(String body, String fromIp, int totalFee, String trade_no) throws Exception {

        // 创建一个有序集合，微信统一下单接口要求参数需要字典序排序
        Map<String, String> paramsMap = new TreeMap<>();

        // 应用id
        paramsMap.put("appid", wxpayConfig.getAppId());

        // 商户id
        paramsMap.put("mch_id", wxpayConfig.getMchId());

        // 设备号
        paramsMap.put("device_info", "WEB");

        // 随机字符串
        paramsMap.put("nonce_str", WxpayUtil.generateNonceStrUseRand(32));

        // 商品简要描述
        paramsMap.put("body", StringUtils.isEmpty(body) ? "无" : body);

        // 商户订单号
        paramsMap.put("out_trade_no", trade_no);

        // 交易金额
        paramsMap.put("total_fee", String.valueOf(totalFee));

        // 终端ip
        paramsMap.put("spbill_create_ip", fromIp);

        // 支付结果回调地址
        paramsMap.put("notify_url", wxpayConfig.getNotifyUrl());

        // 交易类型
        paramsMap.put("trade_type", SystemConstant.WXPAY_ORDER_NATIVE_TYPE);

        // 商品id，支付方式为Native是，必须传
        paramsMap.put("product_id", WxpayUtil.generateNonceStrUseUUID(8));

        // 签名，一般都是在最后，必须使用上面所有的参数进行的
        // 注意：sign不参与签名，必须作为参数传递给微信，微信会根据sign值进行签名校验
        paramsMap.put("sign", WxpayUtil.generateSignature(paramsMap, wxpayConfig.getMchKey()));
        return WxpayUtil.mapToXml(paramsMap);
    }

    @Override
    public Map<String, String> send2WxpayUnifiedOrder(String wxpayOrderXmlStr) throws Exception {
        // 发送微信官方统一下单，注意：官方要求请求方式必须是post，返回的内容是xml
        String wxpayOrderReturnXmlStr = HttpClient4Util.getResponse4PostByString(wxpayConfig.getOrderUrl(), wxpayOrderXmlStr, SystemConstant.WXPAY_ENCODING_UTF8);

        // 解析返回xml，获取map集合
        return WxpayUtil.xmlToMap(wxpayOrderReturnXmlStr);
    }

    @Override
    public String resolveWxpayOrderNotify(String wxpayOrderNotifyXmlStr) throws Exception {
        // 解析xml字符串，获取map集合

        Map<String, String> wxpayNotifyMap = WxpayUtil.xmlToMap(wxpayOrderNotifyXmlStr);
        String orderNumber = wxpayNotifyMap.get("out_trade_no");

        // 只处理回调成功的结果
        if (SystemConstant.WXPAY_RETURN_SUCCESS.equals(wxpayNotifyMap.get("return_code"))) {
            log.info("------ 微信支付异步回调结果，支付成功");

            // 必须要做签名校验和支付金额校验
            if (WxpayUtil.isSignatureValid(wxpayNotifyMap, wxpayConfig.getMchKey())) {
                log.info("------ 微信支付异步回调结果，签名校验成功");

                log.info("------ 支付成功返回的支付交易号:{}", orderNumber);

                // 先判断是何种交易类型
                if (orderNumber.substring(0, 1).equals("T")) {
                    // 商品购买类型

                    // TODO 发送异步消息队列， 金额校验，修改订单状态-订单号，加积分- userid+price， 减库存 -goodsid+count...
                    Map<String, Object> mapStatus = new HashMap<>();
                    Map<String, Object> mapScore = new HashMap<>();
                    Map<String, Object> mapStock = new HashMap<>();

                    // 订单号
                    mapStatus.put("orderNumber", orderNumber);
                    // 发送消息队列
                    this.sendMessageToQueue(ActiveMqConstant.GOODS_ORDER_STATUS_MQ, mapStatus);

                    // 用户id
                    log.error("------ userId:{}",orderInfoApi.getOrderInfoByOrderNumber(orderNumber).getUserId());
                    mapScore.put("userId", orderInfoApi.getOrderInfoByOrderNumber(orderNumber).getUserId());
                    // 价格
                    mapScore.put("price", orderInfoApi.getOrderInfoByOrderNumber(orderNumber).getPayAmount().intValue());
                    // 发送消息队列
                    this.sendMessageToQueue(ActiveMqConstant.GOODS_ORDER_SCORE_MQ, mapScore);

                    // 订单详情
                    mapStock.put("order_items", JSON.toJSONString(orderItemApi.queryOrderItemByOrderNumber(orderNumber)));
                    // 发送消息队列
                    this.sendMessageToQueue(ActiveMqConstant.GOODS_ORDER_STOCK_MQ, mapStock);

                } else {
                    // 会员充值
                    jedis.setex(orderNumber, 10, "success");
                    log.info("------ 会员充值成功");
                }

                return SystemConstant.WXPAY_RESPONSE_RESULT_SUCCESS;
            } else {
                log.info("------ 微信支付异步回调结果，签名校验失败");
            }
        }

        return SystemConstant.WXPAY_RESPONSE_RESULT_FAIL;
    }


    @Override
    public boolean orderPaySuccess(Integer id) {

        if (wxPayMapper.updateOrderPaySuccess(id) > 0) {
            return true;
        }
        return false;
    }

    @Override
    public TempOrderInfo queryPayInfoByOrderId(String orderId) {

        return wxPayMapper.selectPayInfoByOrderId(orderId);
    }

    @Override
    public TempOrderInfo queryVipPayInfoByOrderId(String orderId) {

        return wxPayMapper.selectVipPayInfoByOrderId(orderId);
    }

    /**
     * Created on 2021/6/25
     * Author: GongMingJie
     *
     * @param
     * @return Description: 向指定的消息队列发送消息
     */
    public void sendMessageToQueue(String queueName, Map<String, Object> message) {
        log.info("******  向队列{}，发送1条消息：{}，begin *****", queueName, message);

        // 创建一个目标消息队列（消息容器）
        Destination destination = new ActiveMQQueue(queueName);

        // 向目标队列发送消息
        jmsMessagingTemplate.convertAndSend(destination, JSON.toJSONString(message));

        log.info("******  向队列{}，发送1条消息：{}，end *****", queueName, message);
    }

}
